<template>
  <div class="w-full px-4 py-6 max-w-[900px] mx-auto">
    <h2 class="text-xl font-semibold">语音对话测试页</h2>
    <div class="mt-4 space-x-2">
      <button class="h-9 px-3 rounded-lg bg-[#635BFF] text-white text-sm hover:opacity-90 transition" @click="connect">连接WS</button>
      <button class="h-9 px-3 rounded-lg bg-[#635BFF] text-white text-sm hover:opacity-90 transition" @click="startRecognize">开始说话</button>
      <button class="h-9 px-3 rounded-lg bg-[#635BFF] text-white text-sm hover:opacity-90 transition" @click="stopRecognize">结束说话</button>
      <button class="h-9 px-3 rounded-lg bg-[#635BFF] text-white text-sm hover:opacity-90 transition" @click="startTTS">播放回复（TTS_START）</button>
      <button class="h-9 px-3 rounded-lg bg-[#635BFF] text-white text-sm hover:opacity-90 transition" @click="closeWs">关闭</button>
    </div>
    <div class="mt-4 p-3 rounded bg-gray-50 text-sm whitespace-pre-wrap break-words">
      <div>状态：{{ status }}</div>
      <div class="mt-2">日志：</div>
      <div class="mt-1 max-h-64 overflow-auto">{{ logs.join('\n') }}</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import VoiceWsClient from '@/utils/voiceWs'
import AudioCapturer from '@/utils/audioCapture'
import PcmPlayer from '@/utils/pcmPlayer'

const status = ref('idle')
const logs = ref<string[]>([])

let client: VoiceWsClient | null = null
let capturer: AudioCapturer | null = null
let player: PcmPlayer | null = null

const BASE = import.meta.env.VITE_APP_BASE_API || 'http://4a3c718d.r3.cpolar.top'
const CHAT_ID = `chat_${Math.random().toString(36).slice(2, 8)}`
// const CHAT_ID = 'chat_123456'
function log(msg: string) { logs.value.push(`[${new Date().toLocaleTimeString()}] ${msg}`) }

function ensureClient() {
  if (client) return client
  client = new VoiceWsClient(CHAT_ID, { baseURL: BASE })
  client.on('open', () => { status.value = 'connected'; log('ws open') })
  client.on('close', (ev) => { status.value = `closed(${ev.code})`; log(`ws close ${ev.code} ${ev.reason || ''}`) })
  client.on('error', () => { log('ws error') })
  client.on('text', (txt) => { log('text: ' + txt) })
  client.on('binary', (buf) => {
    log('binary len=' + buf.byteLength)
    // 将下行 PCM16/22050 播放
    if (!player) player = new PcmPlayer({ sampleRate: 22050 })
    player.feed(buf)
  })
  return client
}

function connect() {
  ensureClient().connect()
  ensureClient().sendJSON({ type: 'START' })
}

async function startRecognize() {
  ensureClient().sendJSON({ type: 'RECOGNIZE_START' })
  if (!capturer) capturer = new AudioCapturer({ targetSampleRate: 16000, chunkMs: 200 })
  await capturer.start((chunk) => {
    client?.sendBinary(chunk)
  })
  status.value = 'recording'
  log('recognize start')
}

function stopRecognize() {
  capturer?.stop()
  ensureClient().sendJSON({ type: 'RECOGNIZE_STOP' })
  status.value = 'recognized'
  log('recognize stop')
}

function startTTS() {
  ensureClient().sendJSON({ type: 'TTS_START' })
  log('tts start')
}

function closeWs() {
  capturer?.stop()
  player?.stop()
  client?.sendJSON({ type: 'END' })
  client?.close(1000, 'bye')
  client = null
  status.value = 'closed'
}
</script>




